package com.bkgy.modularbx.coil_track_stats.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bkgy.modularbx.coil_track_stats.domain.TrackingStats1630;
import com.bkgy.modularbx.coil_track_stats.dto.*;
import com.bkgy.modularbx.coil_track_stats.mapper.TrackingStats1630Mapper;
import com.bkgy.modularbx.coil_track_stats.service.CoilCountDailyService;
import com.bkgy.modularbx.coil_track_stats.service.TrackingStats1630Service;
import com.bkgy.modularbx.coil_track_stats.util.StatSummaryBuilder;
import com.bkgy.modularbx.coil_track_stats.vo.TrackStatsQueryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author dell
* @description 针对表【T_COIL_TRACKING_STATS_1630(连退1630分卷全流程统计表)】的数据库操作Service实现
* @createDate 2025-10-27 11:07:19
*/
@Service
public class TrackingStats1630ServiceImpl extends ServiceImpl<TrackingStats1630Mapper, TrackingStats1630>
    implements TrackingStats1630Service{

    @Autowired
    private TrackingStats1630Mapper trackingStats1630Mapper;
    
    @Autowired
    private CoilCountDailyService coilCountDailyService;
    @Override
    public CoilTrackStatsDTO getStatsByDateRange(Integer dateType, String startDate, String endDate) {
        // 查询数据
        List<TrackingStats1630> statsList;

        // 根据dateType选择查询方式
        if (dateType != null && dateType == 2) {
            // 按月统计：使用SQL查询实现
            statsList = trackingStats1630Mapper.selectMonthlyStats(startDate, endDate);
        } else {
            // 按日统计：使用原有查询方式
            QueryWrapper<TrackingStats1630> queryWrapper = new QueryWrapper<>();
            queryWrapper.between("toc_date", startDate, endDate)
                    .orderByAsc("toc_date");
            statsList = this.list(queryWrapper);
        }
        
        // 构建返回结果
        CoilTrackStatsDTO result = new CoilTrackStatsDTO();
        
        // 设置符合卷重统计数据
        //result.setProductionStatsDTO(buildProductionStats(statsList, startDate, endDate, dateType));
        
        // 设置缺陷原因统计数据
        result.setTrackStatsResultDTO(buildDefectResult(statsList, startDate, endDate, dateType));
        
        // 设置损失重量统计数据
        result.setLossStatsDTO(buildLossStats(statsList));
        
        return result;
    }
    /**
     * 构建缺陷原因统计数据
     */
    private DefectResultDTO buildDefectResult(List<TrackingStats1630> statsList, String startDate, String endDate, Integer dateType) {
        DefectResultDTO defectResult = new DefectResultDTO();
        
        // 生成完整的日期范围列表
        List<String> fullDateRange = generateDateRange(startDate, endDate, dateType);
        
        // 创建数据映射，便于查找
        Map<String, TrackingStats1630> statsMap = statsList.stream()
            .collect(Collectors.toMap(TrackingStats1630::getTocDate, stats -> stats));
        
        // 构建完整的日期列表和数据列表
        List<String> tocDates = new ArrayList<>();
        List<BigDecimal> defectWeightCntRate = new ArrayList<>();
        List<BigDecimal> defectYieldCntRate = new ArrayList<>();
        List<BigDecimal> defectQualityCntRate = new ArrayList<>();
        List<BigDecimal> defectWeightLossRate = new ArrayList<>();
        List<BigDecimal> defectYieldLossRate = new ArrayList<>();
        List<BigDecimal> defectQualityLossRate = new ArrayList<>();
        
        for (String date : fullDateRange) {
            tocDates.add(date);
            
            TrackingStats1630 stats = statsMap.get(date);
            if (stats != null) {
                defectWeightCntRate.add(stats.getDefectWeightCntRate() != null ? stats.getDefectWeightCntRate() : BigDecimal.ZERO);
                defectYieldCntRate.add(stats.getDefectYieldCntRate() != null ? stats.getDefectYieldCntRate() : BigDecimal.ZERO);
                defectQualityCntRate.add(stats.getDefectQualityCntRate() != null ? stats.getDefectQualityCntRate() : BigDecimal.ZERO);
                defectWeightLossRate.add(stats.getDefectWeightLossRate() != null ? stats.getDefectWeightLossRate() : BigDecimal.ZERO);
                defectYieldLossRate.add(stats.getDefectYieldLossRate() != null ? stats.getDefectYieldLossRate() : BigDecimal.ZERO);
                defectQualityLossRate.add(stats.getDefectQualityLossRate() != null ? stats.getDefectQualityLossRate() : BigDecimal.ZERO);
            } else {
                // 数据库中没有该日期的数据，设置为0
                defectWeightCntRate.add(BigDecimal.ZERO);
                defectYieldCntRate.add(BigDecimal.ZERO);
                defectQualityCntRate.add(BigDecimal.ZERO);
                defectWeightLossRate.add(BigDecimal.ZERO);
                defectYieldLossRate.add(BigDecimal.ZERO);
                defectQualityLossRate.add(BigDecimal.ZERO);
            }
        }
        
        defectResult.setTocDates(tocDates);
        defectResult.setDefectWeightCntRate(defectWeightCntRate);
        defectResult.setDefectYieldCntRate(defectYieldCntRate);
        defectResult.setDefectQualityCntRate(defectQualityCntRate);
        defectResult.setDefectWeightLossRate(defectWeightLossRate);
        defectResult.setDefectYieldLossRate(defectYieldLossRate);
        defectResult.setDefectQualityLossRate(defectQualityLossRate);
        
        return defectResult;
    }
    
    /**
     * 构建损失重量统计数据
     */
    private LossStatsDTO buildLossStats(List<TrackingStats1630> statsList) {
        LossStatsDTO lossStats = new LossStatsDTO();
        
        // 计算重量原因损失重量总和
        BigDecimal weightLoss = statsList.stream()
            .map(TrackingStats1630::getDefectWeightLoss)
            .filter(Objects::nonNull)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 计算质量原因损失重量总和
        BigDecimal qualityLoss = statsList.stream()
            .map(TrackingStats1630::getDefectQualityLoss)
            .filter(Objects::nonNull)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 计算成材率原因损失重量总和
        BigDecimal yieldLoss = statsList.stream()
            .map(TrackingStats1630::getDefectYieldLoss)
            .filter(Objects::nonNull)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        lossStats.setWeightLoss(weightLoss);
        lossStats.setQualityLoss(qualityLoss);
        lossStats.setYieldLoss(yieldLoss);
        
        return lossStats;
    }
    
    /**
     * 生成完整的日期范围列表
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param dateType 日期类型：1-按日，2-按月
     * @return 日期范围列表
     */
    private List<String> generateDateRange(String startDate, String endDate, Integer dateType) {
        List<String> dateRange = new ArrayList<>();
        
        if (dateType != null && dateType == 2) {
            // 按月统计：生成月份范围
            LocalDate start = LocalDate.parse(startDate + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            LocalDate end = LocalDate.parse(endDate + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            
            while (!start.isAfter(end)) {
                dateRange.add(start.format(DateTimeFormatter.ofPattern("yyyy-MM")));
                start = start.plusMonths(1);
            }
        } else {
            // 按日统计：生成日期范围
            LocalDate start = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            LocalDate end = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            
            while (!start.isAfter(end)) {
                dateRange.add(start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                start = start.plusDays(1);
            }
        }
        
        return dateRange;
    }

    @Override
    public String getCoilStatInfos(Integer dateType, String startDate, String endDate) {
        List<DefectReasonStatDTO> defectStats;
        
        // 根据日期类型选择不同的查询方法
        if (dateType != null && dateType == 2) {
            // 按月统计
            defectStats = trackingStats1630Mapper.selectTopSteelGradesMonthly(startDate, endDate);
        } else {
            // 按日统计（默认）
            defectStats = trackingStats1630Mapper.selectTopSteelGrades(startDate, endDate);
        }
        
        // 获取分卷数统计信息
        Map<String, BigDecimal> coilCountStats = getCoilCountStats(dateType, startDate, endDate);
        BigDecimal countDifference = coilCountStats.get("countDifference");
        BigDecimal totalAddedCosts = coilCountStats.get("totalAddedCosts");
        
        // 调用StatSummaryBuilder中的公共方法构建统计信息文本（新格式）
        return StatSummaryBuilder.buildNewStatSummary(defectStats, countDifference, totalAddedCosts);
    }
    
    /**
     * 获取分卷数统计信息
     * @param dateType 日期类型
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 包含分卷数差值和费用的Map
     */
    private Map<String, BigDecimal> getCoilCountStats(Integer dateType, String startDate, String endDate) {
        // 创建查询参数对象
        TrackStatsQueryVO queryVO = new TrackStatsQueryVO();
        queryVO.setDateType(dateType);
        queryVO.setStartDate(startDate);
        queryVO.setEndDate(endDate);
        queryVO.setLineType("CAL1630"); // 使用连退1630产线
        
        // 获取分卷数统计数据
        CoilCountStatsDTO coilCountStats = coilCountDailyService.getCountStats(queryVO);
        
        // 计算各项指标的总和
        BigDecimal totalAddedCosts = sumList(coilCountStats.getAddedCosts());
        BigDecimal totalRecommendCounts = sumList(coilCountStats.getRecommendCounts());
        BigDecimal totalActualCounts = sumList(coilCountStats.getActualCounts());
        
        // 计算实际分卷数与推荐分卷数的差值
        BigDecimal countDifference = totalActualCounts.subtract(totalRecommendCounts);
        
        // 返回分卷数差值和费用
        Map<String, BigDecimal> result = new HashMap<>();
        result.put("countDifference", countDifference);
        result.put("totalAddedCosts", totalAddedCosts);
        
        return result;
    }
    
    /**
     * 计算列表中所有BigDecimal值的总和
     * @param list BigDecimal列表
     * @return 总和
     */
    private BigDecimal sumList(List<BigDecimal> list) {
        if (list == null || list.isEmpty()) {
            return BigDecimal.ZERO;
        }
        
        return list.stream()
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

}




